// Copyright 2008 Senary
// See credits.txt for details.

// This file is part of Omega VII.

// Omega VII is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Omega VII is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Omega VII.  If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include <windows.h> //required by adll.h
#include <map>
#include <set>
#include <list>
#include <string>
#include <vector>

#include "sdk_engine/adll.h"

#include "Spaceship.h"
#include "Planet.h"
#include "Level.h"
#include "star.h"
#include "Stardust.h"
#include "UnitDecorator.h"
#include "UIManager.h"
#include "MessageBoard.h"
#include "SfxManager.h"

// forward declaration of input manager
class InputManager;
class UnitDecorator;
class Camera;

/*
 Singleton class.
*/
class GameManager
{
private:
	//the sound file
	SOUND* ayesir;
	SOUND* yescaptain;
	SOUND* givemeabreak;
	SOUND* newordersforme;
	SOUND* idunworkforu;

	// Singleton Instance
	static GameManager* _pInstance;

	//engine variables
	ENGINE_VARS* ev;

	// The currently loaded Level
	Level _level;

	//controls the user view
	Camera* _pCamera;

	//display message on the left side of screen
	MessageBoard _messageBoard;

	// class that is responsible for handling keyboard/mouse
	InputManager* _inputManager;

	// class that is responsible for handling keyboard/mouse
	UIManager* _UIManager;

	// class that is responsible for handling decorations around objects
	UnitDecorator* _unitDecorator;

	// class that is responsible for handling animations
	SfxManager _sfxManager;

	// maps space objects (planets, ships, moons, asteroids, ...) to GameStudio Entities
	std::map<SpaceObject*, ENTITY*> _spaceObjectMap;

	// list of all objects that died during the current frame
	std::vector<SpaceObject*> _deadObjects;
	
	// This links to all the planets... for operations that only have to loop through planets.
	std::vector<SpaceObject*> _planets;

	// Contains all currently selected objects.
	std::set<SpaceObject*> _selectedObjects;

	// Stores information about the different players (human, CPU)
	std::vector<Player *> _players;

	// Draws a rectangle. Vectors represent screen coordinates in pixels. Their z value is ignored.
	// TODO: refactor this... doesn't really belong here I think.
	void drawRect(Vector corner1, Vector corner2, Vector color);

protected:
	GameManager(void);

public:
	~GameManager(void);

	//singleton method
	static GameManager* getInstance(void);

	// getter for the level
	Level& getLevel();

	//getter for camera
	Camera* getCamera() const;

	//getter for inputManager
	InputManager* getInputManager() const;

	//getter for UIManager
	UIManager* getUIManager() const;

	//getter for SfxManager
	SfxManager & getSfxManager();


	// Returns the object corresponding to a given entity
	// If the ENTITY does not exist, returns 0.
	SpaceObject* findObject(ENTITY const* ent);
	
	//Returns the entity corresponding to a given object
	ENTITY* findEntity(SpaceObject* so);

	// finds the planet closest to the specified object.
	SpaceObject* findNearestPlanet(SpaceObject const* so);

	// finds the planet closest to the specified object.
	SpaceObject* findNearestEnemy(SpaceObject const* so);

	//factory method for instantiating spaceship
	Spaceship* createSpaceship(SpaceshipType type);

	// notifies the gameManager that a space object has died
	void objectDied(SpaceObject * who);

	// Adds a space object and the corresponding entity to the map of space objects.
	// Used when loading a level
	void addSpaceship(Spaceship* so, ENTITY* ent);

	// delete a spaceship and the corresponding GameStudio entity.
	void removeSpaceship(Spaceship* so);
	
	// adds a planet
	void addPlanet(Planet* so, ENTITY* ent);

	// delete a planet and the corresponding GameStudio entity.
	void removePlanet(Planet* so);
	
	// Adds a player
	// Used when loading a level
	void addPlayer(Player* p);

	// getter for the player list
	std::vector<Player*> const& getPlayers() const;

	// Initialises the game engine
	// Returns true on success, false otherwise
	bool initEngine();

	// This function contains the main game loop. It only returns when the
	// Game finishes.
	void gameLoop();

	//collect data from game world then update values in game engine
	void updateGameEngine(void);

	//scan keyboard for input and update camera position
	void updateCamera(float timestep, float totalTime);

	// Resets the Game, i.e. destroys all the objects.
	void reset();

	//flash message on left side of screen
	void appendMessage(string const& message);

	//let external classes add back seleted object
	void addSelectedObject(SpaceObject* so);

	
	// IO is sourced out into it's own class
	friend class InputManager;

	// Allows testing of the GameManager
	friend class LevelLoadTest;
	friend class SpaceObjectMovementTest;




	
};
